// --- Copyright (c) 2006-2008 Stefan Kyntchev ---
// This software is written and copyrighted by Stefan Kyntchev 
// and BeyondPod Team members. All rights are reserved.
// Author contact: support@beyondpod.mobi
// ------------------------------------------------------------------------
// This file is part of BeyondPod RSS Feed Reader and Podcast manager
// (www.codeplex.com/BeyondPod) 
// BeyondPod is free software: you can redistribute it and/or modify 
// it under the terms of the GNU General Public License as published by 
// the Free Software Foundation, either version 3 of the License, or 
// (at your option) any later version. 
//  
// BeyondPod is distributed in the hope that it will be useful, 
// but WITHOUT ANY WARRANTY; without even the implied warranty of 
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
// GNU General Public License for more details. 
//  
// You should have received a copy of the GNU General Public License
// along with BeyondPod. If not, see <http://www.gnu.org/licenses/>
// ------------------------------------------------------------------------
// COPYRIGHT NOTICE: This copyright notice may NOT be removed, obscured or modified 
// without written consent from the author.
// --- End copyright notice --- 


/*
 * Created by: Stefan Kyntchev
 * Created: Monday, February 26, 2007
 */

using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Text;

namespace svs.Mobile.BeyondMedia.FeedCore.RSS.Templates
{
	public class DocumentTemplate : TemplateBase
	{
		private static List<KeyValuePair<string, string>> m_Template;
		private static int m_ItemsContentIndex = -1;
		private readonly List<FeedItemTemplate> m_Items = new List<FeedItemTemplate>();
		private readonly NextPageTemplate m_NextPage = new NextPageTemplate(TemplateTypes.RSS);
		private readonly int m_PageSize;
		private readonly PrevPageTemplate m_PrevPage = new PrevPageTemplate(TemplateTypes.RSS);
		private readonly string m_SaveFile;
		private FeedTemplate m_Feed;
		private Encoding m_FeedEncoding = Encoding.UTF8;
		private int m_PageNumber;
		private StreamWriter m_HTMLWriter = null;
		private bool m_HasHiddenReadItems = false;

		public DocumentTemplate(string i_SaveFile, int i_PageSize, TemplateTypes type) : base(type)
		{
			m_SaveFile = i_SaveFile;
			m_PageSize = i_PageSize;

			for (m_ItemsContentIndex = 0; m_ItemsContentIndex != Template.Count; m_ItemsContentIndex++)
			{
				if (Template[m_ItemsContentIndex].Value == "#FEED_ITEMS#")
					break;
			}
		}

		#region Properties
		public override List<KeyValuePair<string, string>> Template
		{
			get
			{
				if (m_Template == null)
				{
					m_TemplateFileName = "RSSDocument.htm";
					m_Template = LoadTemplate();
				}
				return m_Template;
			}
		}

		public bool IsAggregateFeed { get; set; }

		public DateTime? LastRetrievalDate { get; set; }

		public bool HasHiddenReadItems
		{
			get { return m_HasHiddenReadItems; }
			set { m_HasHiddenReadItems = value; }
		}

		public int FeedAge { get; set; }

		public int LastItemID { get; set; }

		public FeedTemplate Feed
		{
			get { return m_Feed; }
			set { m_Feed = value; }
		}

		public Encoding FeedEncoding
		{
			get { return m_FeedEncoding; }
			set { m_FeedEncoding = value; }
		}

		public List<FeedItemTemplate> Items
		{
			get { return m_Items; }
		}

		public bool HideReadItems { get; set; }

		#endregion


		private string GetCurrentFileName()
		{
			string retVal = m_SaveFile;
			if (m_PageNumber > 0)
			{
				retVal =
					Path.Combine(Path.GetDirectoryName(m_SaveFile),
					             Path.GetFileNameWithoutExtension(m_SaveFile) + m_PageNumber + Path.GetExtension(m_SaveFile));
			}
			return retVal;
		}

		private string GenerateNextFileName()
		{
			m_PageNumber++;
			return GetCurrentFileName();
		}

		public bool SaveAsHtml()
		{
			CoreHelper.WriteTraceEntry("Generating Feed HTML...");

			string fName = GetCurrentFileName(); // call 1 times only!
			string stTemp = fName + ".tmp";

			try
			{
				FileStream fs = new FileStream(stTemp,FileMode.Create, FileAccess.Write,FileShare.Read);
				m_HTMLWriter = new StreamWriter(fs);
				WritePreItems();

				WriteFeedItems();

				WritePostItems();

				m_HTMLWriter.Close();
				m_HTMLWriter = null;

				File.Copy(stTemp, fName, true);
    		return true;
			}
			catch (Exception ex)
			{
				throw new ApplicationException("Error loading feed Content! Reason: " + ex.Message, ex);
			}
			finally
			{
				if (m_HTMLWriter != null)
					m_HTMLWriter.Close();

				if (File.Exists(stTemp))
					File.Delete(stTemp);  

				CoreHelper.WriteTraceEntry("DONE Generating Feed HTML!");
			}
		}

		private void WritePreItems()
		{
			for(int i= 0; i < m_ItemsContentIndex; i++)
			{
				WriteTemplateFor(Template[i], m_HTMLWriter);
			}
		}

		private void WritePostItems()
		{
			if(m_ItemsContentIndex + 1 >= Template.Count)
				return;

			for (int i = (m_ItemsContentIndex + 1); i < Template.Count; i++)
			{
				WriteTemplateFor(Template[i], m_HTMLWriter);
			}
		}

		protected override void WriteContentFor(string Key, StreamWriter sr)
		{
			switch (Key)
			{
				case "#IS_OLD_MSG#":
					if (FeedAge > 0)
					{
						FeedOldTemplate fot = new FeedOldTemplate(TemplateType);
						fot.DaysOld = FeedAge.ToString();
						fot.ToHtml(sr);
					}
					else if(!IsAggregateFeed && LastRetrievalDate.HasValue)
					{
						new FeedLastUpdateTemplate(TemplateType)
						          	{
						          		LastUpdateDate = CoreHelper.FormatDateTime(LastRetrievalDate)
						          	}.ToHtml(sr);
					}
					break;

				case "#FEED_ENCODING#":
					if (FeedEncoding != null)
					{
						sr.Write(FeedEncoding.WebName);
					}
					break;

				case "#SYS_COLOR_A#":
					{
						sr.Write( CoreHelper.SYS_COLOR_A );
						break;
					}

				case "#LAST_ITEM_ID#":
					{
						sr.Write(LastItemID);
						break;
					}

				case "#FEED_TEMPLATE#":
					m_Feed.ToHtml(sr);
					break;

				case "#SHOW_ALL_READ_ITEMS_VISIBILITY#":
					sr.Write(m_HasHiddenReadItems ? "block" : "hidden");
					break;

				case "#NEXT_PREV_FEED_VISIBILITY#":
					sr.Write(IsAggregateFeed ? "hidden" : "block");
					break;

				case "#SHOW_SHORTCUTS_VISIBILITY#":
					sr.Write(m_HasHiddenReadItems ? "hidden":"block");
					break;

				case "#DOCUMENT_FONT_SIZE#":
					if (string.IsNullOrEmpty(Configuration.DefaultDocFontSize))
					{
						sr.Write("medium");
					}
					else
					{
						sr.Write(Configuration.DefaultDocFontSize);
					}
					break;
			}
		}

		private void WriteFeedItems()
		{
			int pageItemId = 1;

			foreach (FeedItemTemplate item in m_Items)
			{
				item.FeedPageItemID = (pageItemId++).ToString();
				item.ToHtml(m_HTMLWriter);
		
				//Check if we have to break the file
				if (m_HTMLWriter.BaseStream.Length <= m_PageSize*1024) continue;
				
				string prevFile = Path.GetFileName(GetCurrentFileName());

				//Close current file
				m_NextPage.NextPageFile = Path.GetFileName(GenerateNextFileName()) + "?BeyondPodPage";
				m_NextPage.ToHtml(m_HTMLWriter);
				LastItemID = pageItemId-1;
				WritePostItems();
				m_HTMLWriter.Close();
				pageItemId = 1;

				//Open the next file
				FileStream fs = new FileStream(GetCurrentFileName(), FileMode.Create, FileAccess.Write, FileShare.Read);
				m_HTMLWriter = new StreamWriter(fs);
				WritePreItems();
				m_PrevPage.PrevPageFile = prevFile + "?BeyondPodPage";
				m_PrevPage.ToHtml(m_HTMLWriter);
			}

			LastItemID = pageItemId-1;
		}

		public static void RefreshTemplate()
		{
			m_Template = null;
		}
	}
}